package com.zegoto.design.design.behavior.visitor;


import java.util.ArrayList;
import java.util.List;

// 定义图形结构接口
interface Shape {
    void accept(Visitor visitor);
}

// 具体的图形类
class Circle implements Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    public double getRadius() {
        return radius;
    }

    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

class Rectangle implements Shape {
    private double width;
    private double height;

    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    public double getWidth() {
        return width;
    }

    public double getHeight() {
        return height;
    }

    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

// 访问者接口
interface Visitor {
    void visit(Circle circle);
    void visit(Rectangle rectangle);
}

// 具体的访问者类
class AreaVisitor implements Visitor {
    private double area;

    public void visit(Circle circle) {
        area += Math.PI * circle.getRadius() * circle.getRadius();
    }

    public void visit(Rectangle rectangle) {
        area += rectangle.getWidth() * rectangle.getHeight();
    }

    public double getArea() {
        return area;
    }
}

class PerimeterVisitor implements Visitor {
    private double perimeter;

    public void visit(Circle circle) {
        perimeter += 2 * Math.PI * circle.getRadius();
    }

    public void visit(Rectangle rectangle) {
        perimeter += 2 * (rectangle.getWidth() + rectangle.getHeight());
    }

    public double getPerimeter() {
        return perimeter;
    }
}

// 对象结构类
class ShapeContainer {

    private List<Shape> shapes;

    public ShapeContainer() {
        shapes = new ArrayList<>();
    }

    public void addShape(Shape shape) {
        shapes.add(shape);
    }

    public void accept(Visitor visitor) {
        for (Shape shape : shapes) {
            shape.accept(visitor);
        }
    }
}

public class VisitorDemo {

    public static void main(String[] args) {
        ShapeContainer container = new ShapeContainer();
        container.addShape(new Circle(3));
        container.addShape(new Rectangle(4, 5));
//        container.addShape(new Circle(5));

        AreaVisitor areaVisitor = new AreaVisitor();
        container.accept(areaVisitor);
        System.out.println("Total area: " + areaVisitor.getArea());

        PerimeterVisitor perimeterVisitor = new PerimeterVisitor();
        container.accept(perimeterVisitor);
        System.out.println("Total perimeter: " + perimeterVisitor.getPerimeter());
    }
}
